/* 
 * File:   TablaSimplex.h
 * Author: bastian
 *
 * Created on 14 de mayo de 2011, 23:29
 */

#ifndef STDIO_H
#include <stdio.h>
#define STDIO_H
#endif

#ifndef FRACCIONES_H
#include "Fracciones.h"
#define FRACCIONES_H
#endif

#ifndef MATRICES_H
#include "Matrices.h"
#define MATRICES_H
#endif

typedef struct{

    Matriz *MatrizAsociada;
    Matriz *BetaMenosUno;
    Fraccion *b;
    Fraccion *Xb;
    Fraccion *Zj_Cj;
    Matriz *A;
    Fraccion *Z;
    int FilaPivotePrimal;
    int ColumnaPivotePrimal;
    int FilaPivoteDual;
    int ColumnaPivoteDual;
    int Filas;
    int Columnas;
    
}TablaSimplex;


void Mostrar_Z(TablaSimplex *tabla);
void Mostrar_Zj_Cj(TablaSimplex *tabla);
void Mostrar_BetaMenosUno(TablaSimplex *tabla);
void Mostrar_Xb(TablaSimplex *tabla);
void Mostrar_b(TablaSimplex *tabla);
void Mostrar_A(TablaSimplex *tabla);

TablaSimplex *TablaSimplex_new(int filas, int columnas){
    
   
    TablaSimplex *tabla = (TablaSimplex *) malloc(sizeof(TablaSimplex));
    
    tabla->BetaMenosUno = Matriz_new(filas-1,filas-1);
    tabla->Zj_Cj = (Fraccion *) malloc((columnas-1)*sizeof(Fraccion));
    tabla->Xb = (Fraccion *) malloc((filas-1)*sizeof(Fraccion));
    tabla->b = (Fraccion *) malloc((filas-1)*sizeof(Fraccion));
    tabla->A= Matriz_new(filas-1,columnas-filas);
    tabla->FilaPivotePrimal= -1;
    tabla->ColumnaPivotePrimal= -1;
    tabla->FilaPivoteDual= -1;
    tabla->ColumnaPivoteDual= -1;
    tabla->Filas=filas;
    tabla->Columnas=columnas;
    
    return tabla;
}

void TablaSimplex_Matriz_a_Tabla(TablaSimplex *tabla, Matriz *m){

    tabla->MatrizAsociada = m;
    
    int filas = tabla->Filas;
    int columnas = tabla->Columnas;
    
    int fila_b=0;
    int columna_b=(int) fabs(filas-columnas);
    
    
    //Beta^-1
    for(int i = 0; i< filas-1; i++){
        for(int j= 0; j< filas-1; j++){
                tabla->BetaMenosUno->elementos[i][j]=m->elementos[fila_b][columna_b];
                columna_b++;
        }
        fila_b++;
        columna_b=(int) fabs(filas-columnas);
    }
    
    //Zj-Cj
    for( int i=0; i< columnas-1; i++){
        tabla->Zj_Cj[i]=m->elementos[filas-1][i];
        
    }
    
    //Xb
    for(int i = 0; i< filas-1; i++ ){
        tabla->Xb[i]=m->elementos[i][columnas-1];
    }
    
    //si es la primera tabla Xb=b
    
    for(int i = 0; i< filas-1; i++ ){
        tabla->b[i]=m->elementos[i][columnas-1];
    }
    //de lo contrario b= Xb*Beta
    //IMPLEMENTAR
    
    //Z
    tabla->Z= &m->elementos[filas-1][columnas-1];

    //A*Beta^-1
    for(int i = 0; i< tabla->A->filas; i++){
        for (int j = 0; j < tabla->A->columnas; j++){
            tabla->A->elementos[i][j]=m->elementos[i][j];
        } 
    }

}


void TablaSimplex_Tabla_a_Matriz(TablaSimplex *tabla, Matriz *m){

    //Se asume que m esta inicializada
    
    //A
    for(int i = 0; i< tabla->A->filas; i++){
        for(int j=0; j< tabla->A->columnas; j++ ){
            m->elementos[i][j]=tabla->A->elementos[i][j];
        }
    }
    
    //Beta^-1    
    for(int i = 0; i < tabla->BetaMenosUno->filas; i++){
        int a = (int) fabs( tabla->Columnas - tabla->Filas);
        
        for(int j = 0; j< tabla->BetaMenosUno->columnas; j++){
            m->elementos[i][a]=tabla->BetaMenosUno->elementos[i][j];
            a++;
        }        
    }
    
    //Zj-Cj
    for(int i = 0; i< (tabla->Columnas)-1; i++)
        m->elementos[tabla->Filas-1][i]=tabla->Zj_Cj[i];
    
    //Xb
    for(int i = 0; i< tabla->Filas-1; i++)
        m->elementos[i][tabla->Columnas-1]=tabla->Xb[i];
    
    //Z
    m->elementos[tabla->Filas-1][tabla->Columnas-1]=*tabla->Z;

}

void TablaSimplex_MostrarTabla(TablaSimplex *tabla){

    
    Mostrar_BetaMenosUno(tabla);
    Mostrar_Xb(tabla);    
    Mostrar_b(tabla); 
    Mostrar_Zj_Cj(tabla);
    Mostrar_A(tabla);
    Mostrar_Z(tabla);
}


void Mostrar_Z(TablaSimplex *tabla){
    printf("\nZ: ");
    Fraccion_Mostrar(tabla->Z);
    getchar();
}

void Mostrar_Zj_Cj(TablaSimplex *tabla){

    printf("\nZj-Cj:\n");
    for(int i = 0; i< tabla->Columnas-1; i++){
        Fraccion_Mostrar(&tabla->Zj_Cj[i]);
        printf(" ");
    }
    getchar();
}

void Mostrar_BetaMenosUno(TablaSimplex *tabla){
    
    printf("\nB ^ -1:\n");
    Matriz_Mostrar(tabla->BetaMenosUno);
    getchar();
}

void Mostrar_Xb(TablaSimplex *tabla){
    
    printf("\nXb:\n");
    for(int i = 0; i< tabla->Filas-1; i++){
        Fraccion_Mostrar(&tabla->Xb[i]);
        getchar();
    }

}

void Mostrar_b(TablaSimplex *tabla){
    
    printf("\nb:\n");
    for(int i = 0; i< tabla->Filas-1; i++){
        Fraccion_Mostrar(&tabla->b[i]);
        getchar();
    }

}

void Mostrar_A(TablaSimplex *tabla){
    
    printf("\nA:\n");
    Matriz_Mostrar(tabla->A);
    getchar();

}

